package com.mydemo.utils.dataUtils.updateUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.mydemo.utils.dataUtils.DataOperation;
import com.mydemo.utils.dataUtils.DataUtil;
import com.mydemo.utils.dataUtils.JsonAndFile.FileRW;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.mydemo.utils.dataUtils.JsonAndFile.Deserialize.deserialize;
import static com.mydemo.utils.dataUtils.JsonAndFile.Serialize.serialize;

public class Update<T> implements DataOperation<T> {

    private Class<T> clazz;
    private String table;

    public Update(Class<T> clazz, String table) {
        this.clazz = clazz;
        this.table = table;
    }

    @Override
    public T execute() {
        return (T) "update";
    }

    /**
     * 更新存储在指定文件中的列表中，所有具有给定属性值的实例为新对象。
     *
     * @param updateCol    需要更新的列。
     * @param newValue    新的实例，用于替换所有匹配条件的实例。
     * @param selectCol    要匹配的属性名。
     * @param selectValue 与指定属性名对应的值，用于匹配实例。
     */
    public <T> void update(String updateCol, Object newValue, String selectCol, Object selectValue, boolean allOrNot) {
        String jsonRead = FileRW.FileRead(table);// 从指定文件读取JSON数据
        List<T> objectList = deserialize(jsonRead, (Class<T>) clazz);// 反序列化JSON数据
        // 使用stream流处理列表，替换所有匹配条件的实例为newObject
        objectList = (List<T>) objectList.stream()
                .map(item -> {
                    JSONObject itemAsJson = JSON.parseObject(JSON.toJSONString(item));
                    if (selectValue != null && itemAsJson.get(selectCol) != null && itemAsJson.get(selectCol).equals(selectValue)) {
                        itemAsJson.put(updateCol, newValue);
                    }
                    return JSON.parseObject(itemAsJson.toJSONString(), clazz);
                })
                .collect(Collectors.toList());
        String newJSON = serialize(objectList);// 序列化更新后的列表为JSON字符串
        FileRW.FileWrite(table, newJSON);// 将更新后的JSON数据写回到文件
    }
    /**
     * 根据实体对象的Id更新指定对象的所有字段。
     *
     * @param newObject    新的实体对象，用于更新所有字段。
     */
    public Update<T> updateObject(T newObject) {
        try {
            Field idField = findField(clazz, "Id");
            idField.setAccessible(true);
            int id = (int) idField.get(newObject);
            String jsonRead = FileRW.FileRead(table);
            List<T> objectList = deserialize(jsonRead, (Class<T>) clazz);

            objectList = objectList.stream()
                    .map(item -> {
                        try {
                            Field itemIdField = findField(clazz, "Id");
                            itemIdField.setAccessible(true);
                            if (itemIdField.get(item).equals(id)) {
                                return newObject;
                            }
                        } catch (Exception e) {
                            throw new RuntimeException("无法访问或获取Id字段", e);
                        }
                        return item;
                    })
                    .collect(Collectors.toList());

            String newJSON = serialize(objectList);
            FileRW.FileWrite(table, newJSON);
        } catch (Exception e) {
            throw new RuntimeException("更新操作失败", e);
        }

        return this;
    }
    /**
     * 根据Id更新指定字段。
     *
     * @param id             实体的Id
     * @param newValue      新的实体对象，用于更新
     * @param updateCol      需要更新的列
     */
    public Update<T> updateById(int id, Object newValue, String updateCol) {
        update(updateCol, newValue, "id", id, false);
        return this;
    }

    private <T> Field findField(Class<T> clazz, String fieldName) {
        while (clazz != null) {
            try {
                return clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException ignored) {
                clazz = (Class<T>) clazz.getSuperclass();
            }
        }
        throw new RuntimeException("无法找到字段 " + fieldName);
    }

}
